package vip.liux.contracts.infrastructure.threads;

import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 动态可调参数的线程池任务执行器
 * <p>
 * 支持运行时动态调整核心线程数、最大线程数、队列容量、存活时间等参数。
 * 线程池队列支持动态扩容，适合高并发后端业务场景。
 * <p>
 * 建议搭配监控与告警使用，及时发现线程池耗尽等风险。
 *
 * @author liuxinhh
 */
public class DynamicThreadPoolExecutor extends ThreadPoolTaskExecutor {

    /**
     * 可动态扩容的阻塞队列
     */
    private final ResizableCapacityLinkedBlockingQueue<Runnable> resizableQueue;
    /**
     * 当前核心线程数
     */
    private volatile int corePoolSize;
    /**
     * 当前最大线程数
     */
    private volatile int maxPoolSize;

    /**
     * 构造函数，初始化线程池参数及可扩容队列
     *
     * @param corePoolSize     核心线程数
     * @param maxPoolSize      最大线程数
     * @param keepAliveSeconds 线程空闲存活时间(秒)
     * @param queueCapacity    队列容量
     */
    public DynamicThreadPoolExecutor(int corePoolSize, int maxPoolSize,
                                     long keepAliveSeconds, int queueCapacity) {
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = maxPoolSize;
        this.resizableQueue = new ResizableCapacityLinkedBlockingQueue<>(queueCapacity);

        // 设置线程池参数
        super.setCorePoolSize(corePoolSize);
        super.setMaxPoolSize(maxPoolSize);
        super.setKeepAliveSeconds((int) keepAliveSeconds);
        super.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 重写 createQueue，避免 setQueue (废弃方法)
        // 不再调用 super.setQueue
        super.setWaitForTasksToCompleteOnShutdown(true);
        super.setAwaitTerminationSeconds(60);
        // 初始化
        super.initialize();
    }

    /**
     * 重写队列创建，使用可扩容阻塞队列
     */
    @Override
    protected BlockingQueue<Runnable> createQueue(int capacity) {
        return this.resizableQueue;
    }

    /**
     * 动态调整核心线程数
     *
     * @param corePoolSize 新的核心线程数 (>=0 且 <= 最大线程数)
     */
    public synchronized void setCorePoolSize(int corePoolSize) {
        if (corePoolSize < 0 || corePoolSize > maxPoolSize) {
            throw new IllegalArgumentException("corePoolSize 必须大于等于0且小于等于maxPoolSize");
        }
        this.corePoolSize = corePoolSize;
        super.setCorePoolSize(corePoolSize);
        adjustPoolSize();
    }

    /**
     * 动态调整最大线程数
     *
     * @param maxPoolSize 新的最大线程数 (>= 核心线程数)
     */
    public synchronized void setMaxPoolSize(int maxPoolSize) {
        if (maxPoolSize < corePoolSize) {
            throw new IllegalArgumentException("maxPoolSize 必须大于等于 corePoolSize");
        }
        this.maxPoolSize = maxPoolSize;
        super.setMaxPoolSize(maxPoolSize);
        adjustPoolSize();
    }

    /**
     * 动态调整线程空闲存活时间
     *
     * @param keepAliveSeconds 空闲时间（秒，>= 0）
     */
    public synchronized void setKeepAliveSeconds(long keepAliveSeconds) {
        if (keepAliveSeconds < 0) {
            throw new IllegalArgumentException("keepAliveSeconds 必须大于等于0");
        }
        getThreadPoolExecutor().setKeepAliveTime(keepAliveSeconds, TimeUnit.SECONDS);
    }

    /**
     * 动态调整队列容量
     *
     * @param capacity 新的队列容量 (>0)
     */
    public synchronized void setQueueCapacity(int capacity) {
        if (capacity <= 0) {
            throw new IllegalArgumentException("Queue capacity 必须大于0");
        }
        resizableQueue.setCapacity(capacity);
    }

    /**
     * 调整线程池参数，确保核心线程数/最大线程数合法
     */
    private void adjustPoolSize() {
        ThreadPoolExecutor executor = super.getThreadPoolExecutor();
        // 顺序不能反，否则可能抛异常
        executor.setMaximumPoolSize(maxPoolSize);
        executor.setCorePoolSize(corePoolSize);
    }

    // ========== 线程池运行指标 ==========

    /**
     * 获取活跃线程数
     *
     * @return 活跃线程数
     */
    public int getActiveCount() {
        return super.getThreadPoolExecutor().getActiveCount();
    }

    /**
     * 获取已完成任务数
     *
     * @return 已完成任务数
     */
    public long getCompletedTaskCount() {
        return super.getThreadPoolExecutor().getCompletedTaskCount();
    }

    /**
     * 获取当前线程池线程数
     *
     * @return 线程池线程数
     */
    public int getPoolSize() {
        return super.getThreadPoolExecutor().getPoolSize();
    }

    /**
     * 获取队列当前待执行任务数
     *
     * @return 队列长度
     */
    public int getQueueSize() {
        return resizableQueue.size();
    }

    /**
     * 获取线程池负载因子（活跃线程数/最大线程数）
     *
     * @return 负载因子
     */
    public double getLoadFactor() {
        int maxThreads = this.maxPoolSize;
        int activeThreads = getActiveCount();
        return maxThreads > 0 ? (double) activeThreads / maxThreads : 0;
    }
}